﻿using System;
using System.Collections.Generic;
using System.Data;
using visinia.SmartEngine;
using visinia.SmartEngine.Cache;
using viWiki.Classes;
using viWiki.Providers;

namespace viWiki.Controllers
{
    public class WikiPageController
    {
        #region ACCESS
        /// <summary>
        /// Gets all the WikiPage
        /// </summary>
        /// <returns>List of all WikiPage</returns>
        public static List<WikiPage> GetWikiPages()
        {
            List<WikiPage> list = (List<WikiPage>)DataCache.GetCache("WikiPage");
            if (list == null)
            {
                list = FillWikiPages(viWikiDataProvider.Provider.GetWikiPages());
                DataCache.SetCache("WikiPage", list);
            }
            return list;
        }

        /// <summary>
        /// Gets the WikiPage by its name
        /// </summary>
        /// <param name="Name"></param>
        /// <returns></returns>
        public static WikiPage GetWikiPage(string Name)
        {
            string name = Name.Trim();
            return GetWikiPages().Find(p => string.Compare(p.Name, name, true) == 0);
        }

        /// <summary>
        /// Gets the WikiPage contents with the wiki page links resolved
        /// </summary>
        /// <param name="wikiPageId"></param>
        /// <returns></returns>
        public static string GetWikiPageHtmlContent(int WikiPageId)
        {
            WikiPage rawPage = GetWikiPages().Find(p => p.WikiPageId == WikiPageId);            
            //update the wiki pages links
            string pageData =  FormateController.RawStringToHtml(rawPage.Content);
            //toc
             string data =  FormateController.TOC(pageData);
             return data;
        }

        /// <summary>
        /// Gets the WikiPage
        /// </summary>
        /// <param name="wikiPageId"></param>
        /// <returns></returns>
        public static WikiPage GetWikiPage(int WikiPageId)
        {
            return GetWikiPages().Find(p => p.WikiPageId == WikiPageId);
        }

        /// <summary>
        /// Gets the wiki pages of the specified Namespace
        /// </summary>        
        public static List<WikiPage> GetWikiPagesByNamespace(int NamespaceInfoId)
        {
            return GetWikiPages().FindAll(p => p.NamespaceInfoId == NamespaceInfoId);
        }
                
        private const string KEY_WIKIPAGE_BY_URL = "wikipageByUrl_{0}";
        private const int WIKIPAGE_BY_URL_EXPIRY = 20;

        /// <summary>
        /// Generates the url for a wiki page
        /// </summary>
        /// <param name="page">The wiki page for which to generate url</param>
        /// <returns>returns the wiki page url</returns>
        private static string GenerateUrl(WikiPage page)
        {
            /*****************************************************************************************/
            // Wiki Page URL = Wiki/WikiPageId/Namespace/some.thing.imp.aspx
            /*****************************************************************************************/
            string key = string.Format(KEY_WIKIPAGE_BY_URL, page.WikiPageId);
            string URL = (string)DataCache.GetCache(key);
            if (URL == null)
            {
                string wikipageid = page.WikiPageId.ToString();
                string nspace = NamespaceController.GetNamespace(page.NamespaceInfoId).Name;
                string url = page.Url;
                URL = WikiController.WikiUrlSeparator + "/" + wikipageid + "/" + nspace + "/" + url + ".aspx";
                DataCache.SetCache(key, URL, new TimeSpan(0, WIKIPAGE_BY_URL_EXPIRY, 0));
            }
            return URL;
        }
        #endregion
        
        #region DATA
        /// <summary>
        /// Adds a new WikiPage
        /// </summary>
        /// <param name="page">The WikiPage to be added </param>
        public static int AddWikiPage(WikiPage page)
        {
            IDataReader dr = viWikiDataProvider.Provider.AddWikiPage(page.NamespaceInfoId, page.Name, page.Content, page.Date, page.Author, page.Url);
            int index = 0;
            while (dr.Read())
            {
                if (dr[0] != Convert.DBNull)
                    index = (int)dr[0];
            }
            dr.Close();
            WikiPageLinkController.AddWikiPageLinks(index, FormateController.BuildPageLinks(page.Content));
            DataCache.DeleteCacheMultiple("WikiPage");
            return index;
        }

        /// <summary>
        /// Updates the WikiPage
        /// </summary>
        /// <param name="page"></param>
        public static void UpdateWikiPage(WikiPage page)
        {
            viWikiDataProvider.Provider.UpdateWikiPage(page.WikiPageId, page.NamespaceInfoId, page.Name, page.Content, page.Date, page.Author, page.Url);
            WikiPageLinkController.AddWikiPageLinks(page.WikiPageId, FormateController.BuildPageLinks(page.Content));
            DataCache.DeleteCacheMultiple("WikiPage");
        }

        /// <summary>
        /// Deletes the WikiPage
        /// </summary>
        /// <param name="wikiPageId">Id of the WikiPage to Delete</param>
        public static void DeleteWikiPage(int WikiPageId)
        {
            viWikiDataProvider.Provider.DeleteWikiPage(WikiPageId);
            WikiPageLinkController.DeleteWikiPageLinks(WikiPageId);
            DataCache.DeleteCacheMultiple("WikiPage");
        }

        /// <summary>
        /// Deletes the WikiPage
        /// </summary>
        /// <param name="page">The WikiPage to Delete</param>
        public static void DeleteWikiPage(WikiPage page)
        {
            DeleteWikiPage(page.WikiPageId);
        }
        #endregion

        #region HELPERS
        private static WikiPage FillWikiPage(IDataReader dr)
        {
            while (dr.Read())
            {
                return ActualRead(dr, true);
            }
            return null;
        }
        private static List<WikiPage> FillWikiPages(IDataReader dr)
        {
            List<WikiPage> list = new List<WikiPage>();
            while (dr.Read())
            {
                list.Add(ActualRead(dr, false));
            }
            dr.Close();
            return list;
        }
        private static WikiPage ActualRead(IDataReader dr, bool CloseDataReader)
        {
            WikiPage page = new WikiPage();
            if (dr["WikiPageId"] != Convert.DBNull)
                page.WikiPageId = (int)dr["WikiPageId"];
            if (dr["NamespaceInfoId"] != Convert.DBNull)
                page.NamespaceInfoId = (int)dr["NamespaceInfoId"];
            if (dr["Name"] != Convert.DBNull)
                page.Name = (string)dr["Name"];            
            if (dr["Date"] != Convert.DBNull)
                page.Date = (DateTime)dr["Date"];
            if (dr["Author"] != Convert.DBNull)
                page.Author = (string)dr["Author"];
            if (dr["Url"] != Convert.DBNull)
                page.Url = (string)dr["Url"];
            if (dr["Content"] != Convert.DBNull)
                page.Content = (string)dr["Content"];
            //update the image urls and wiki page url
            page.Url = WebRoots.GetWebRoot + GenerateUrl(page);
            page.Content = ImageController.ResolveImagesForDisplay(page.Content);
            if (CloseDataReader)
                dr.Close();
            return page;
        }
        #endregion
    }
}
